package com.guducat.collegeWeb.service;

import com.guducat.collegeWeb.dto.request.ArticleEditDTO;
import com.guducat.collegeWeb.dto.response.ArticleDetailDTO;
import com.guducat.collegeWeb.dto.response.ArticleListDTO;
import com.guducat.collegeWeb.dto.response.PageResultDTO;
import com.guducat.collegeWeb.entity.Article;
import com.guducat.collegeWeb.exception.ResourceNotFoundException;
import com.guducat.collegeWeb.mapper.ArticleMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ArticleService {
    private final ArticleMapper articleMapper;

    public ArticleService(ArticleMapper articleMapper) {
        this.articleMapper = articleMapper;
    }

    /**
     * 获取文章详情（前台用户访问）
     * @param newsId 文章ID
     * @return 文章详情
     */
    public ArticleDetailDTO getArticleDetail(Integer newsId) {
        Article article = articleMapper.selectByNewsId(newsId);
        if (article == null) {
            throw new ResourceNotFoundException("文章不存在");
        }
        return convertToDetailDTO(article);
    }

    /**
     * 获取文章详情（管理员访问，包含更多字段）
     * @param newsId 文章ID
     * @return 文章详情（包含完整信息）
     */
    public ArticleDetailDTO adminGetArticleDetail(Integer newsId) {
        Article article = articleMapper.selectByNewsId(newsId);
        if (article == null) {
            throw new ResourceNotFoundException("文章不存在");
        }
        return convertToAdminDetailDTO(article);
    }

    /**
     * 更新文章（前台用户）
     * @param newsId 文章ID
     * @param articleEditDTO 文章编辑信息
     */
    @Transactional
    public void updateArticle(Integer newsId, ArticleEditDTO articleEditDTO) {
        // 检查文章是否存在
        Article article = articleMapper.selectByNewsId(newsId);
        if (article == null) {
            throw new ResourceNotFoundException("文章不存在");
        }

        // 更新文章信息
        article.setCategory(articleEditDTO.getCategory());
        article.setTitle(articleEditDTO.getTitle());
        article.setContentHtml(articleEditDTO.getContentHtml());

        // 保存更新
        articleMapper.updateArticle(article);
    }

    /**
     * 更新文章（管理员）
     * 可更新更多字段，包括URL、发布时间等
     * @param newsId 文章ID
     * @param articleEditDTO 文章编辑信息
     */
    @Transactional
    public void adminUpdateArticle(Integer newsId, ArticleEditDTO articleEditDTO) {
        // 检查文章是否存在
        Article article = articleMapper.selectByNewsId(newsId);
        if (article == null) {
            throw new ResourceNotFoundException("文章不存在");
        }

        // 更新文章信息
        article.setCategory(articleEditDTO.getCategory());
        article.setTitle(articleEditDTO.getTitle());
        article.setContentHtml(articleEditDTO.getContentHtml());

        // 管理员可以更新更多字段
        if (articleEditDTO.getUrl() != null) {
            article.setUrl(articleEditDTO.getUrl());
        }

        if (articleEditDTO.getContentText() != null) {
            article.setContentText(articleEditDTO.getContentText());
        } else {
            // 如果未提供contentText，则从HTML中提取（这部分在Mapper中已实现）
        }

        if (articleEditDTO.getPubTime() != null) {
            article.setPubTime(articleEditDTO.getPubTime());
        }

        // 更新section字段
        if (articleEditDTO.getSection() != null) {
            article.setSection(articleEditDTO.getSection());
        }

        // 更新爬取时间为当前时间（表示最后更新时间）
        article.setCrawlTime(ZonedDateTime.now());

        // 保存更新（使用完整更新方法）
        articleMapper.updateByNewsId(article);
    }

    /**
     * 创建文章（前台用户）
     * @param articleEditDTO 文章编辑信息
     * @return 新文章ID
     */
    @Transactional
    public Integer createArticle(ArticleEditDTO articleEditDTO) {
        Article article = new Article();
        article.setCategory(articleEditDTO.getCategory());
        article.setTitle(articleEditDTO.getTitle());
        article.setContentHtml(articleEditDTO.getContentHtml());
        article.setPubTime(ZonedDateTime.now());

        // 保存文章
        articleMapper.insertArticle(article);

        return article.getNewsId();
    }

    /**
     * 创建文章（管理员）
     * 可设置更多字段，包括URL、发布时间等
     * 如果提供了newsId，则使用该ID创建文章，否则自动生成
     * @param articleEditDTO 文章编辑信息
     * @return 新文章ID
     */
    @Transactional
    public Integer adminCreateArticle(ArticleEditDTO articleEditDTO) {
        Article article = new Article();
        article.setCategory(articleEditDTO.getCategory());
        article.setTitle(articleEditDTO.getTitle());
        article.setContentHtml(articleEditDTO.getContentHtml());

        // 设置发布时间，如果未提供则使用当前时间
        if (articleEditDTO.getPubTime() != null) {
            article.setPubTime(articleEditDTO.getPubTime());
        } else {
            article.setPubTime(ZonedDateTime.now());
        }

        // 设置URL（如果提供）
        if (articleEditDTO.getUrl() != null) {
            article.setUrl(articleEditDTO.getUrl());
        }

        // 设置文本内容（如果提供）
        if (articleEditDTO.getContentText() != null) {
            article.setContentText(articleEditDTO.getContentText());
        }

        // 设置section（如果提供）
        if (articleEditDTO.getSection() != null) {
            article.setSection(articleEditDTO.getSection());
        }

        // 设置爬取时间为当前时间
        article.setCrawlTime(ZonedDateTime.now());

        // 检查是否提供了newsId
        if (articleEditDTO.getNewsId() != null) {
            // 检查ID是否已存在
            if (articleMapper.existsById(articleEditDTO.getNewsId())) {
                throw new IllegalArgumentException("文章ID已存在，请使用其他ID");
            }

            // 使用指定的ID创建文章
            article.setNewsId(articleEditDTO.getNewsId());
            articleMapper.insertArticleWithId(article);
        } else {
            // 随机生成一个唯一的ID（6位数字）
            int randomId;
            do {
                randomId = 100000 + (int)(Math.random() * 900000); // 生成6位随机数
            } while (articleMapper.existsById(randomId));

            article.setNewsId(randomId);
            articleMapper.insertArticleWithId(article);
        }

        return article.getNewsId();
    }

    /**
     * 删除文章
     * @param newsId 文章ID
     */
    @Transactional
    public void deleteArticle(Integer newsId) {
        // 检查文章是否存在
        Article article = articleMapper.selectByNewsId(newsId);
        if (article == null) {
            throw new ResourceNotFoundException("文章不存在");
        }

        // 删除文章
        articleMapper.deleteArticle(newsId);
    }

    /**
     * 转换为前台详情DTO（包含基本信息）
     */
    private ArticleDetailDTO convertToDetailDTO(Article article) {
        ArticleDetailDTO dto = new ArticleDetailDTO();
        BeanUtils.copyProperties(article, dto);
        return dto;
    }

    /**
     * 转换为管理员详情DTO（包含所有字段）
     */
    private ArticleDetailDTO convertToAdminDetailDTO(Article article) {
        ArticleDetailDTO dto = new ArticleDetailDTO();
        // 复制所有属性
        BeanUtils.copyProperties(article, dto);

        // 确保所有需要的字段都被设置
        dto.setNewsId(article.getNewsId());
        dto.setCategory(article.getCategory());
        dto.setTitle(article.getTitle());
        dto.setPubTime(article.getPubTime());
        dto.setContentHtml(article.getContentHtml());
        dto.setUrl(article.getUrl());

        // 添加管理员需要的额外字段
        dto.setContentText(article.getContentText());
        dto.setCrawlTime(article.getCrawlTime());

        return dto;
    }

    /**
     * 转换为列表DTO（不包含详细内容）
     */
    private ArticleListDTO convertToListDTO(Article article) {
        ArticleListDTO dto = new ArticleListDTO();
        dto.setNewsId(article.getNewsId());
        dto.setCategory(article.getCategory());
        dto.setTitle(article.getTitle());
        dto.setPubTime(article.getPubTime());
        dto.setSection(article.getSection());

        // 提取文章摘要（最多100个字符）
        String contentText = article.getContentText();
        if (contentText != null && !contentText.isEmpty()) {
            dto.setContentPreview(contentText.length() > 100 ? contentText.substring(0, 100) + "..." : contentText);
        } else {
            dto.setContentPreview("");
        }

        return dto;
    }

    /**
     * 获取最新文章列表（分页）
     * @param pageNum 页码（从1开始）
     * @param pageSize 每页记录数
     * @return 分页结果
     */
    public PageResultDTO<ArticleListDTO> getLatestArticles(int pageNum, int pageSize) {
        // 计算偏移量
        int offset = (pageNum - 1) * pageSize;

        // 查询总记录数
        long total = articleMapper.countAll();

        // 查询当前页数据
        List<Article> articles = articleMapper.selectLatestNewsWithPage(pageSize, offset);

        // 转换为DTO
        List<ArticleListDTO> dtoList = articles.stream()
                .map(this::convertToListDTO)
                .collect(Collectors.toList());

        // 返回分页结果
        return new PageResultDTO<>(dtoList, total, pageNum, pageSize);
    }

    /**
     * 根据分类获取文章列表（分页）
     * @param category 分类
     * @param pageNum 页码（从1开始）
     * @param pageSize 每页记录数
     * @return 分页结果
     */
    public PageResultDTO<ArticleListDTO> getArticlesByCategory(String category, int pageNum, int pageSize) {
        // 计算偏移量
        int offset = (pageNum - 1) * pageSize;

        // 查询总记录数
        long total = articleMapper.countByCategory(category);

        // 查询当前页数据
        List<Article> articles = articleMapper.selectByCategoryWithPage(category, pageSize, offset);

        // 转换为DTO
        List<ArticleListDTO> dtoList = articles.stream()
                .map(this::convertToListDTO)
                .collect(Collectors.toList());

        // 返回分页结果
        return new PageResultDTO<>(dtoList, total, pageNum, pageSize);
    }

    /**
     * 根据关键词搜索文章（分页）
     * @param keyword 关键词
     * @param pageNum 页码（从1开始）
     * @param pageSize 每页记录数
     * @return 分页结果
     */
    public PageResultDTO<ArticleListDTO> searchArticlesByKeyword(String keyword, int pageNum, int pageSize) {
        // 计算偏移量
        int offset = (pageNum - 1) * pageSize;

        // 查询总记录数
        long total = articleMapper.countByKeyword(keyword);

        // 查询当前页数据
        List<Article> articles = articleMapper.selectByKeywordWithPage(keyword, pageSize, offset);

        // 转换为DTO
        List<ArticleListDTO> dtoList = articles.stream()
                .map(this::convertToListDTO)
                .collect(Collectors.toList());

        // 返回分页结果
        return new PageResultDTO<>(dtoList, total, pageNum, pageSize);
    }

    /**
     * 根据section筛选文章（分页）
     * @param section 学院/教务处等行政机构信息
     * @param pageNum 页码（从1开始）
     * @param pageSize 每页记录数
     * @return 分页结果
     */
    public PageResultDTO<ArticleListDTO> getArticlesBySection(String section, int pageNum, int pageSize) {
        // 计算偏移量
        int offset = (pageNum - 1) * pageSize;

        // 查询总记录数
        long total = articleMapper.countBySection(section);

        // 查询当前页数据
        List<Article> articles = articleMapper.selectBySectionWithPage(section, pageSize, offset);

        // 转换为DTO
        List<ArticleListDTO> dtoList = articles.stream()
                .map(this::convertToListDTO)
                .collect(Collectors.toList());

        // 返回分页结果
        return new PageResultDTO<>(dtoList, total, pageNum, pageSize);
    }

    /**
     * 多条件搜索文章（分页）
     * @param keyword 关键词（可为null或空字符串）
     * @param category 分类（可为null或空字符串）
     * @param section 学院（可为null或空字符串）
     * @param pageNum 页码（从1开始）
     * @param pageSize 每页记录数
     * @return 分页结果
     */
    public PageResultDTO<ArticleListDTO> searchWithMultipleConditions(
            String keyword, String category, String section, int pageNum, int pageSize) {

        // 计算偏移量
        int offset = (pageNum - 1) * pageSize;

        // 处理空字符串为null
        keyword = (keyword != null && keyword.trim().isEmpty()) ? null : keyword;
        category = (category != null && category.trim().isEmpty()) ? null : category;
        section = (section != null && section.trim().isEmpty()) ? null : section;

        // 查询总记录数
        long total = articleMapper.countWithMultipleConditions(keyword, category, section);

        // 查询当前页数据
        List<Article> articles = articleMapper.searchWithMultipleConditions(
                keyword, category, section, pageSize, offset);

        // 转换为DTO
        List<ArticleListDTO> dtoList = articles.stream()
                .map(this::convertToListDTO)
                .collect(Collectors.toList());

        // 返回分页结果
        return new PageResultDTO<>(dtoList, total, pageNum, pageSize);
    }

}
